%{
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define DATE_FORMAT ("%Y/%B/%d\t%T  (%Z %z)")
#define ARRAY_SZ (256)

FILE *sounds=NULL, *resists=NULL, *flags=NULL, *races=NULL, *genos=NULL, *sizes=NULL;
int counter = 0;  //  tracks the total number of items seen.  I think int is safe for this...
FILE* startfile(char* classname) {
	time_t curtime = time((time_t*)0);
	char* datestring = calloc(ARRAY_SZ, sizeof(char));
	char* filename = calloc(ARRAY_SZ, sizeof(char));
	FILE* out;
	
	strftime(datestring, ARRAY_SZ, DATE_FORMAT, localtime(&curtime));
	snprintf(filename, ARRAY_SZ, "%s.java", classname);
	
	out = fopen(filename, "w");
	assert(out != NULL);
	
	fprintf(out, 
	"/**\n* Automatically generated on %s\n**/\npackage termint.game.monsters;\npublic enum %s {\n\t",
	datestring, classname);
	
	return out;
}

void endfile(FILE* out, char* classname, char* type) {
	assert(out != NULL);
	fseek(out, -1L, SEEK_CUR);
	fprintf(out,
	";\n\t/** purely internal id */\n\tprivate %s value;\n\tprivate %s(%s v) {\n\t\tthis.value = v;\n\t}\n\
	private %s(%s copy) {\n\t\tthis.value = copy.value;\n\t}\n}\n",
	type, classname, type, classname, classname);
	fclose(out);
}

%}

%debug
%expect 2
%union {char* s; int i; long l;}

%token <s> SOUND 
%token <s> RESIST 
%token <s> FLAG 
%token <s> SIZE 
%token <s> RACE 
%token <s> GENO 
%token <i> INT
%token <l> LONG
%token THE_END
%token DEFINE
%token IFNDEF
%token ENDIF

%type <s> geno_list

%initial-action {
	sounds = startfile("Sound");
	resists = startfile("Resistance");
	flags = startfile("Flag");
	races = startfile("Race");
	genos = startfile("Generation");
	sizes = startfile("Size");
}

%%

input: IFNDEF DEFINE definitions ENDIF {
	endfile(sounds, "Sound", "int");
	endfile(resists, "Resistance", "int");
	endfile(flags, "Flag", "int");
	endfile(races, "Race", "Flag");
	endfile(genos, "Generation", "int");
	endfile(sizes, "Size", "int");
	YYACCEPT;
};

definitions:  DEFINE SOUND number  	{ 	fprintf(sounds, "%s(%d),", $2, counter++); }
			| DEFINE SOUND SOUND  	{ 	fprintf(sounds, "%s(%s),", $2, $3); }
			| DEFINE RESIST number  { 	fprintf(resists, "%s(%d),", $2, counter++); }
			| DEFINE FLAG number  	{ 	fprintf(flags, "%s(%d),", $2, counter++); }
			| DEFINE SIZE number  	{ 	fprintf(sizes, "%s(%d),", $2, counter++); }
			| DEFINE SIZE SIZE  	{ 	fprintf(sizes, "%s(%s),", $2, $3); }
			| DEFINE RACE FLAG  	{ 	fprintf(races, "%s(Flag.%s),", $2, $3); }
			| DEFINE GENO number  	{ 	fprintf(genos, "%s(%d),", $2, counter++); }
			| DEFINE GENO '(' geno_list ')'	{ 	fprintf(genos, "/* %s: (%s) */", $2, $4); }
			| definitions definitions 	  {  }
;

geno_list:    GENO						{ $$ = $1; }
			| geno_list '|' geno_list   { asprintf(&$$, "%s|%s", $1, $3); }
;

number: INT | LONG { };

%%
extern int yylineno;
extern char* yytext;
int yyerror(char *s, int lineNumber) {
  fprintf(stderr, "Error: %s at %d: '%s'\n", s, yylineno, yytext);
  return 0;
}

int main(int argc, char** argv) {
	FILE* in_file = fopen("nhsrc/monflag.h", "r");
	yyrestart(in_file);
	yyparse();
	fclose(in_file);
	
	printf("Done\n");
	return 0;
}
